/**
 * @file FreeRTOS_app.c
 * @author liufeng (liufeng@injoinic.com)
 * @brief FreeRTOS task.
 * @version 0.1
 * @date 2024-11-07
 *
 * @copyright Copyright (c) 2024  injoinic
 *
 */

#include "FreeRTOS.h"
#include "FreeRTOS_app.h"
#include "bsp_mpu6050_handler.h"
#include "queue.h"
#include "task.h"

TaskHandle_t StartTask_Handle = NULL;          // 用于任务创建
TaskHandle_t PrintTask_Handle = NULL;
TaskHandle_t mpu6050HandlerTask_Handle = NULL; // mpu6050处理任务
TaskHandle_t mpu6050UnpackTask_Handle = NULL;  // mpu6050解包任务

void StartTask(void* argument);
void PrintTask(void* argument);
void mpu6050UnpackTask(void* argument);

typedef struct
{
    void (*pxTaskCode)(void*);
    const char* const pcName;
    const uint16_t usStackDepth;
    void* const pvParameters;
    uint32_t uxPriority;
    void** const pxCreatedTask;
} task_attribute;

static const task_attribute task_table[] = {
    {mpu6050HandlerTask, "mpu6050HandlerTask", 256, NULL, 1, &mpu6050HandlerTask_Handle},
    {mpu6050UnpackTask, "mpu6050UnpackTask", 256, NULL, 1, &mpu6050UnpackTask_Handle},
    // {PrintTask, "PrintTask", 128, NULL, 1, &PrintTask_Handle},
};

void FreeRTOS_app()
{
    BaseType_t xReturn = pdPASS;
    xReturn = xTaskCreate(StartTask, "StartTask", 128, NULL, 1, &StartTask_Handle);
    configASSERT(xReturn);

    vTaskStartScheduler();
}

/* -------------------------------------------------------------------------- */
/*                                   start任务                                 */
/* -------------------------------------------------------------------------- */

void StartTask(void* argument)
{
    taskENTER_CRITICAL(); // 进入临界区

    // 根据task_table结构体数组，创建所有任务
    uint16_t task_num = sizeof(task_table) / sizeof(task_attribute);
    for (uint16_t i = 0; i < task_num; i++) {
        BaseType_t xReturn = xTaskCreate(
            task_table[i].pxTaskCode,
            task_table[i].pcName,
            task_table[i].usStackDepth,
            task_table[i].pvParameters,
            task_table[i].uxPriority,
            task_table[i].pxCreatedTask
        );
        configASSERT(xReturn);
    }

    vTaskDelete(StartTask_Handle); // 使命完成，删除

    taskEXIT_CRITICAL();           // 退出临界区
}

/* -------------------------------------------------------------------------- */
/*                                   print任务                                 */
/* -------------------------------------------------------------------------- */

void PrintTask(void* argument)
{
    while (1) {
        printf("Hello,world\r\n");
        vTaskDelay(1000);
    }
}

/* -------------------------------------------------------------------------- */
/*                                mpu6050数据解包任务                          */
/* -------------------------------------------------------------------------- */

void mpu6050UnpackTask(void* argument)
{
    float ax = 0, ay = 0, az = 0;
    float gx = 0, gy = 0, gz = 0;
    float temperature = 0;
    uint8_t* buffer_addr = 0; // 待处理的缓冲区地址

    while (1) {
        // 获取消息队列中的缓冲区地址
        xQueueReceive(mpu6050_instance.unpack_queue, &buffer_addr, portMAX_DELAY);

        // 数据处理
        int16_t accel_x_raw = ((int16_t)buffer_addr[0] << 8) | buffer_addr[1];
        int16_t accel_y_raw = ((int16_t)buffer_addr[2] << 8) | buffer_addr[3];
        int16_t accel_z_raw = ((int16_t)buffer_addr[4] << 8) | buffer_addr[5];
        ax = accel_x_raw / 16384.0;
        ay = accel_y_raw / 16384.0;
        az = accel_z_raw / 16384.0;

        int16_t raw = ((int16_t)buffer_addr[6] << 8) | buffer_addr[7];
        temperature = 36.53f + (raw / 340.f);

        int16_t gyro_x_raw = ((int16_t)buffer_addr[8] << 8) | buffer_addr[9];
        int16_t gyro_y_raw = ((int16_t)buffer_addr[10] << 8) | buffer_addr[11];
        int16_t gyro_z_raw = ((int16_t)buffer_addr[12] << 8) | buffer_addr[13];
        gx = gyro_x_raw / 131.0;
        gy = gyro_y_raw / 131.0;
        gz = gyro_z_raw / 131.0;

        // 打印结果
        printf("temprature is %f\r\n", temperature);
        printf("ax: %f, ay: %f, az: %f\r\n", ax, ay, az);
        printf("gx: %f, gy: %f, gz: %f\r\n\r\n", gx, gy, gz);

        // 移动缓冲区的头指针
        mpu6050_instance.mpu6050_data_buff.pf_move_head(&mpu6050_instance.mpu6050_data_buff);
    }
}
